﻿#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>

#include <glib.h>
#include <libsoup/soup.h>

#include "json/json.h"
#include "http.h"
#include "httpext.h"
#include "util.h"
#include "jsonrpc_server.h"

static void http_post(SoupServer *server, SoupMessage *msg, jsonrpc_server *json_server) {
	json_object *obj = jsonrpc_invoke(json_server, msg->request_body->data);
	if (obj) {
		const char *body = json_object_to_json_string(obj);
		soup_message_body_append(msg->response_body, SOUP_MEMORY_COPY, body, strlen(body));
		json_object_put(obj);
	}
	soup_message_headers_append(msg->response_headers, HTTP_HEADER_CONTENT_TYPE, "application/json");

	soup_message_set_status(msg, SOUP_STATUS_OK);
}

void http_print(SoupMessage *msg, const char *path) {
	SoupMessageHeadersIter iter;
	const char *name, *value;
	g_print("%s %s HTTP/1.%d\n", msg->method, path, soup_message_get_http_version(msg));
	soup_message_headers_iter_init(&iter, msg->request_headers);
	while (soup_message_headers_iter_next(&iter, &name, &value)) {
		g_print("%s: %s\n", name, value);
	}
	if (msg->request_body->length) {
		g_print("%s\n", msg->request_body->data);
	}
}

static void allow_cross_domain(SoupMessage *msg) {
	soup_message_headers_append(msg->response_headers, "Access-Control-Allow-Origin", "*");
	soup_message_headers_append(msg->response_headers, "Access-Control-Allow-Headers", HTTP_HEADER_CONTENT_TYPE);
}

static void server_callback(SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *context, gpointer data) {
	jsonrpc_server *json_server = (jsonrpc_server *) data;
	//http_print(msg, path);

	if (!http_ext(server, msg)) {
		if (msg->method == SOUP_METHOD_POST) {
			allow_cross_domain(msg);
			http_post(server, msg, json_server);
		} else if (msg->method == SOUP_METHOD_OPTIONS) {
			allow_cross_domain(msg);
			soup_message_set_status(msg, SOUP_STATUS_OK);
		} else {
			soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
		}
	}
}

int http_start(unsigned int port, const char *name) {
	int ret = 1;

	if (!name) {
		name = "JSON-RPC Server";
	}

	jsonrpc_server *json_server = jsonrpc_server_new();
	SoupServer *soup_server = soup_server_new(SOUP_SERVER_PORT, port, SOUP_SERVER_SERVER_HEADER, name, NULL);
	if (soup_server) {
		soup_server_add_handler(soup_server, NULL, server_callback, (gpointer) json_server, NULL);
		soup_server_run_async(soup_server);

		ret = 0;
	}

	return ret;
}
